iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0

Table of Contents

  • 播放影片
  • 跳過片段
  • 播放音量與速度
  • 時間軸
  • 全螢幕
  • References

Yes
今天要學如何為元素加上事件,完成一個播放器。作者有提供播放器的HTMLCSS內容,我只有增加HTML<input>title屬性,剩下只會跟著作者做出播放器,程式碼是差不多的。

播放影片

原本我想的是從body裡面的容器player去做點選,並且利用布林值當變數做開關,只要選到event.target就執行切換,但這裡只要使用video.paused屬性就能判斷這個影片有沒有在播放,再利用物件可以用任意修改中括號內容的特性,放入三元運算子的結果。

以這個想法再更換播放的圖示。

如果要用父元素body點選子元素,我可能會再加上判斷event.target是否為觸發的區塊。

const video = player.querySelector('.viewer');
const toggle = player.querySelector('.toggle');

function togglePlay(){
  //video.paused判斷影片是否暫停
  const method = video.paused ? 'play' : 'pause'
  //如果是的話就播影片
  video[method]();
}

function updateButton(){
  //video.paused判斷影片是否暫停
  const icon = this.paused ? '►' : '❚❚';
    //如果是的話就換符號
  toggle.textContent = icon;
}

video.addEventListener('click',togglePlay);
video.addEventListener('play',updateButton);
video.addEventListener('pause',updateButton);

toggle.addEventListener('click',togglePlay);

跳過片段

skip按鍵有兩個,所以用forEach()讓每個按鍵都加上監聽器,之後再使用屬性的預設值扣掉目前的秒數就行了,但是屬性的內容是字串,需要轉數值,也可以把Number()換成parseFloat()

const skipButtons = player.querySelectorAll('[data-skip]');
function skip(){
  video.currentTime += Number(this.dataset.skip);
}
skipButtons.forEach(button=>button.addEventListener('click',skip))

播放音量與速度

這邊我可能會想把兩個內容分開,但沒想到作者把兩個range寫在一起,每次range的值跟項目都不一樣,所以用this就可以在觸發事件的當下選到元素,並且change是在更動值的時候觸發,加上mousemove的效果可以隨時更新值。

function handleRangeUpdate(){
  video[this.name] = this.value;  
}

ranges.forEach(range=>range.addEventListener('change',handleRangeUpdate))
ranges.forEach(range=>range.addEventListener('mousemove',handleRangeUpdate))

時間軸

時間軸主要有兩件事,一是可以隨著播放影片,讓時間軸的寬度增加,二是在滑鼠拖曳的時候,可以讓時間軸的位置拉動到某個時間,讓影片從該時間繼續播放。
在試寫這個功能時,計算時間軸跟時間的比例有點難,但讓我感到最困難的是,我希望滑鼠拖曳的時候可以根據拖曳的距離計算時間軸的比例,可選不出比較好的距離或座標屬性跟計算方式,即使做出來的效果也不太好。

在計算滑鼠拖曳的距離與時間的比例,這邊是滑鼠的位移除以時間軸的整個長度,再乘上整支影片的長度,就能直接算出目前的時間,再回到timeupdate事件更新。

function handleProgress(){
  const percent = (video.currentTime/video.duration)*100
  progressBar.style.flexBasis = `${percent}%`;
}

function scrub(event){
  //計算目前的時間
  const scrubTime = (event.offsetX/progress.offsetWidth)*video.duration
  video.currentTime = scrubTime;
}

video.addEventListener('timeupdate',handleProgress)

let mousedown = false;
progress.addEventListener('click',scrub)
progress.addEventListener('mousemove',(event)=>mousedown&&scrub(event)) 
progress.addEventListener('mousedown',()=>mousedown = true) 
progress.addEventListener('mouseup',()=>mousedown = true) 

全螢幕

作者在最後有讓大家去嘗試做一個按鈕觸發全螢幕,不過我不想改變現在介面的樣式,所以把事件綁在video上面,讓畫面被點擊兩下就可以觸發全螢幕。原本寫了事件之後,想說從程式碼去修改尺寸,但是發現作者已經幫大家寫了一個樣式。

.player:fullscreen {
  max-width: none;
  width: 100%;
}

.player:-webkit-full-screen {
  max-width: none;
  width: 100%;
}

原本想說到底該怎麽觸發偽類,後來發現執行requestFullscreen()方法就能觸發全螢幕。

function fullScreen(){
  player.requestFullscreen()
}

video.addEventListener('dblclick',fullScreen)

References

  • w3school
  1. HTML Audio/Video DOM Reference
  2. onclick Event
  3. Fullscreen API requestFullscreen()

上一篇
〈Day25〉用Canvas畫圖
下一篇
〈Day27〉Geolocation API
系列文
廚藝不精也可以,給自己做一份Javascript小火鍋30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言